import { Toast } from 'antd-mobile'
import axios from 'axios'
import type { AxiosError, InternalAxiosRequestConfig } from 'axios'
import store, { login, logout } from '@/store'
import { ApiErrorResult } from '@/types/data'
import history from '@/utils/history'

const baseURL = 'http://geek.itheima.net/v1_0/'
// 正常axios实例
const instance = axios.create({
  baseURL: baseURL,
  timeout: 5000
})
// 用于刷新token实例
const refreshInstance = axios.create({
  baseURL: baseURL,
  timeout: 5000
})

// 添加请求拦截器
instance.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    const {
      loginSlice: { authInfo }
    } = store.getState()
    if (authInfo.token) {
      config.headers.Authorization = `Bearer ${authInfo.token}`
    }
    return config
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)
// 异常请求队列
const requestQueue: Array<InternalAxiosRequestConfig | undefined> = []
// 刷新token状态中
let refreshing = false

// 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    return response
  },
  async function (error: AxiosError<ApiErrorResult>) {
    // 对响应错误做点什么
    if (!error.response) {
      Toast.show('网络繁忙，稍后重试')
    } else {
      // 1,判断是否401报错
      if (error.response.status === 401) {
        const {
          loginSlice: { authInfo }
        } = store.getState()
        // 2,401报错情况下， 判断有无token
        if (authInfo.token && authInfo.refresh_token) {
          /* 异常请求存入队列 */
          requestQueue.push(error.config)
          /* 第一个401请求开始刷新token,后续401请求仅加入队列，不刷新token */
          if (refreshing) return
          refreshing = true
          // 3-1,有token，toke过期，并且有refresh_token，尝试刷新token
          try {
            const {
              data: {
                data: { token }
              }
            } = await refreshInstance({
              url: '/authorizations',
              method: 'put',
              headers: {
                Authorization: `Bearer ${authInfo.refresh_token}`
              }
            })
            // 4-1,token刷新成功,将新token保存到redux
            store.dispatch(login({ token, refresh_token: authInfo.refresh_token }))
            // 5，token，缓存完成，继续原请求
            refreshing = false
            // 6, 重新发起队列中请求
            requestQueue.forEach((request) => {
              instance(request!)
            })
          } catch (error) {
            // 4-2，token刷新失败，说明refresh_token已过期，清空token，，跳转登录页面
            store.dispatch(logout())
            history.replace('/login', { from: history.location.pathname })
          }
        } else {
          // 3-2,无token,直接跳转登录页
          history.replace('/login', { from: history.location.pathname })
        }
      } else {
        Toast.show(error.response.data.message)
      }
    }
    return Promise.reject(error)
  }
)

export default instance
